Join patterns have recently become popular as an approach for providing a higher level synchronization construct for concurrent programming. In particular, join patterns enable a program to atomically capture a set of values from a number of channels or ports. The term “atomic,” as used herein, refers to the ability to commit an entire set of values or to not commit (i.e. “rollback”) an entire set of values. Put more simply, the atomically captured values are handled together as a group and not on an individual basis. Atomically capturing the values enables safe concurrent execution by preventing another process from interfering with the acquisition of values from multiple channels.
Conventional techniques for implementing join patterns involve building automata using low level constructs such as locks. Such low level constructs are difficult to program, are error prone, and suffer from exponential performance degradation. In particular, the use of locks may result in performance deadlocks, such as when a first thread locks a first channel and requests access to a second channel, while a second thread simultaneously locks the second channel and requests access to the first channel. Additionally, locks are designed based on a worst case or “negative” approach. Specifically, locks are implemented to protect multiple threads from accessing and changing a channel at the same time, thereby resulting in inconsistencies. However, if only a single thread requires access to a channel, then locking the channel is an inefficient operation that raises complexity and slows performance while providing minimal benefits.